#include "team_dungeon.h"
#include "Player.h"
#include "scene_logic.h"
#include "team_mgr.h"
#include "activity_module.h"
#include "MonsterCacheData.h"
#include "../share/MessageDef.h"
#include "../share/tplmgr.h"
#include "mail_module.h"
#include "playerinfo_mgr.h"
#include "MapSlot.h"
#include "script_define.h"


CTeamDungeon::CTeamDungeon():
	hp_notify_timer_(*this)
{
	dungeon_state_ = EDungeon_None;
	team_id_ = 0;
}

void CTeamDungeon::PlayerEnterBoss(int32_t playerid, int32_t heroid1, int32_t heroid2, int32_t heroid3)
{
	TPlayerDamageMap::iterator it = player_damage_map_.find(playerid);
	if (it == player_damage_map_.end())
	{
		player_damage_map_[playerid].damage_ = 0;
		player_damage_map_[playerid].hero_damage_.clear();
		if ( heroid1 != 0 )
		{
			player_damage_map_[playerid].hero_damage_[heroid1] = 0;
		}
		if ( heroid2 != 0)
		{
			player_damage_map_[playerid].hero_damage_[heroid2] = 0;
		}
		if ( heroid3 != 0 )
		{
			player_damage_map_[playerid].hero_damage_[heroid3] = 0;
		}
	}
}

void CTeamDungeon::AddPlayerDamage(int32_t playerid, int32_t damage, Json::Value& damagelist)
{
	TPlayerDamageMap::iterator it = player_damage_map_.find(playerid);
	if (it == player_damage_map_.end())
	{
		return;
	}
	CPlayerHeroDamage& herodamage = it->second;
	herodamage.damage_ += damage;

	for (int32_t i = 0; i < damagelist.size(); ++i )
	{
		Json::Value herodamage_json = damagelist[i];
		int32_t heroid = herodamage_json["heroid"].asInt();
		int32_t hdamage = herodamage_json["damage"].asInt();
		herodamage.hero_damage_[heroid] += hdamage;
	}

	BossReduceHp(playerid, damage);
}

void CTeamDungeon::BossReduceHp(int32_t playerid, int32_t damage)
{
	if (isDie() || dungeon_state_ != EDungeon_Start)
	{
		LOG_INFO("default", "boss is die!");
		return;
	}
	if (boss_cur_hp_ >= damage)
	{
		boss_cur_hp_ -= damage;
	}
	else
	{
		boss_cur_hp_ = 0;
	}

	if (isDie())
	{
		// 触发结算通知
		BossDieNotify();
		onBossEnd(true);
		KillBoss(playerid);
		stop_timer_.TimerStop();
	}
}


void CTeamDungeon::StartBoss(int32_t boss_id, int32_t boss_lv, int32_t team_id)
{
	boss_lv_ = boss_lv;
	boss_id_ = boss_id;
	MonsterInfo* bossinfo = MonsterCacheData::GetInstance().GetData(boss_id_);
	if (bossinfo == NULL)
	{
		LOG_ERROR("default", "start boss err MonsterInfo[%d] is null", boss_id_);
		return;
	}
	boss_max_hp_ = bossinfo->mHp + bossinfo->mLvHp * boss_lv_;
	//boss_max_hp_ = 20000;
	boss_cur_hp_ = boss_max_hp_;
	player_damage_map_.clear();
	dungeon_state_ = EDungeon_Start;

	stop_timer_.Init(team_id);

	hp_notify_timer_.TimerInit(1000);
	hp_notify_timer_.TimerStart();
	team_id_ = team_id;
}

bool CTeamDungeon::isDie()
{
	return boss_cur_hp_ <= 0;
}

void CTeamDungeon::BossDieNotify()
{
	Json::Value notify;
	notify["msgid"] = team_boss_die_notify;
	std::string sendstr = JsonWriter(notify);
	
	for (TPlayerDamageMap::iterator it = player_damage_map_.begin(); it != player_damage_map_.end(); ++it)
	{
		Player* player = CSceneLogic::GetInstance().GetPlayerByPlayerID(it->first);
		if ( player == NULL )
		{
			continue;
		}
		player->SendToClient(notify, team_boss_die_notify);
	}
}

void CTeamDungeon::onBossEnd(bool bossdie)
{
	dungeon_state_ = EDungeon_End;

	Json::Value notify;
	notify["msgid"] = team_boss_end_notify;
	notify["win"] = bossdie;
	Json::Value damage_list;
	for (TPlayerDamageMap::iterator it = player_damage_map_.begin(); it != player_damage_map_.end(); ++it)
	{
		CPlayerHeroDamage& herodamage = it->second;
		Json::Value one_player;
		one_player["playerid"] = (int32_t)it->first;
		CPlayerInfo* playerinfo = CPlayerInfoMgr::GetInstance().GetPlayerInfoByPlayerID(it->first);
		if ( playerinfo == NULL)
		{
			continue;
		}
		one_player["name"] = playerinfo->get_name();
		one_player["damage"] = (int32_t)herodamage.damage_;
		Json::Value hero_list;
		for (std::map<int32_t, int32_t>::iterator it_hero = herodamage.hero_damage_.begin(); it_hero != herodamage.hero_damage_.end(); ++it_hero)
		{
			Json::Value one_hero;
			one_hero["heroid"] = (int32_t)it_hero->first;
			one_hero["damage"] = (int32_t)it_hero->second;
			hero_list.append(one_hero);
		}
		one_player["herolist"] = hero_list;
		damage_list.append(one_player);
	}
	const CTeamBossCfg& teamboss_cfg = CTPLManager::GetInstance().GetTeamBossInfo();
	const CTeamBossLv* teamboss_lv = teamboss_cfg.Getbossinfo(boss_lv_);
	if (teamboss_lv == NULL)
	{
		LOG_ERROR("default", "team boss lv[%d] cfg is null!", boss_lv_);
		teamboss_lv = teamboss_cfg.GetDefaultInfo();
	}
	Json::Value mailitem;
	if (teamboss_lv != NULL)
	{
		teamboss_lv->award_kill().GetMailJsonItem(mailitem);
	}

	notify["damage_list"] = damage_list;
	notify["killaward"] = mailitem;

	for (TPlayerDamageMap::iterator it = player_damage_map_.begin(); it != player_damage_map_.end(); ++it)
	{
		Player* player = CSceneLogic::GetInstance().GetPlayerByPlayerID(it->first);
		if (player == NULL)
		{
			continue;
		}
		player->SendToClient(notify, team_boss_end_notify);
	}

	// 如果boss死亡了，给发奖励
	if ( bossdie && teamboss_lv != NULL)
	{
		for (TPlayerDamageMap::iterator it = player_damage_map_.begin(); it != player_damage_map_.end(); ++it)
		{
			Player* player = CSceneLogic::GetInstance().GetPlayerByPlayerID(it->first);
			if (player == NULL)
			{
				continue;
			}
			std::string str = JsonWriter(mailitem);
			MapSlot::GetInstance().GetLuaManagerPtr()->RunScriptFunction(LUA_PlayerManagerScript,
				LUA_ExtendItemToPlayerBackPack, player->GetPlayerId(), (double)player->GetAccount(), str.c_str());
		}
	}
	// 解散队伍
	CTeam* team = CTeamMgr::GetInstance().GetTeam(team_id_);
	if ( team != NULL )
	{
		CTeamMgr::GetInstance().DissolveTeam(*team);
	}
}

void CTeamDungeon::KillBoss(int32_t playerId)
{

}

void CTeamDungeon::NotifyPlayer(int32_t msgid, Json::Value& notify)
{
	for (TPlayerDamageMap::iterator it = player_damage_map_.begin(); it != player_damage_map_.end(); ++it)
	{
		Player* player = CSceneLogic::GetInstance().GetPlayerByPlayerID(it->first);
		if (player == NULL)
		{
			continue;
		}
		player->SendToClient(notify, msgid);
	}
}

void CDungeonStopTimer::TimerActive()
{
	CTeam* team = CTeamMgr::GetInstance().GetTeam(team_id_);
	if ( team == NULL )
	{
		return;
	}
	// 时间到了，组队副本结束
	team->team_dungeon().onBossEnd(false);
}

void CDungeonStopTimer::Init(int32_t teamid)
{
	team_id_ = teamid;
	TimerInit(3 * 60 * 1000);
	TimerStart();
}

void CDungeonHpNotify::TimerActive()
{
	if ( team_dungeon_.dungeon_state() != EDungeon_Start)
	{
		return;
	}
	Json::Value notify;
	notify["msgid"] = team_boss_info_notify;
	notify["maxhp"] = (double)team_dungeon_.boss_max_hp();
	notify["curhp"] = (double)team_dungeon_.boss_cur_hp();

	team_dungeon_.NotifyPlayer(team_boss_info_notify, notify);

	TimerStart();
}

